﻿
using System;
using System.Collections.Generic;

namespace LxCFD
{
    public class ConnectivityAnalysis
    {
        ZoneMirror[] ZonesMirror;
        public void LoadMeshInf(FvMesh mesh)
        {
            ZonesMirror = new ZoneMirror[mesh.Zones.Count];
            for (int i1 = 0; i1 < ZonesMirror.Length; i1++)
            {
                ZonesMirror[i1] = new ZoneMirror();
            }
        }
        protected void reset()
        {
            foreach (var i in ZonesMirror)
            {
                i.PoolID = -2;
                i.LinkedZoneID_Bigger.Clear();
            }
        }
        protected void addRelationShip<T1, T2>(List<T1> zones, List<T2> contacts) where T1 : IConnectivityAnalyzableZone where T2 : IConnectivityAnalyzableContact
        {
            for (int i1 = 0; i1 < zones.Count; i1++)
            {
                int zoneID = zones[i1].GetZoneID();
                ZonesMirror[zoneID].PoolID = -1;
                ZonesMirror[zoneID].IndexInList = i1;
            }
            foreach (var c in contacts)
            {
                c.GetONZoneID(out int smallIDZone, out int bigIDZone);
                if (smallIDZone > bigIDZone)
                {
                    LxTool.Exchange(ref smallIDZone, ref bigIDZone);
                }
                ZonesMirror[smallIDZone].LinkedZoneID_Bigger.Add(bigIDZone);
            }
        }
        public List<ConnectedZones<T1, T2>> SplitByConnectivity<T1, T2>(List<T1> zones, List<T2> contacts) where T1 : IConnectivityAnalyzableZone where T2 : IConnectivityAnalyzableContact
        {
            reset();
            addRelationShip(zones, contacts);
            List<ConnectedZones<T1, T2>> list = new List<ConnectedZones<T1, T2>>();
            //zone
            foreach (var zoneM in ZonesMirror)//遍历zoneMirror更能保证从小到大遍历
            {
                if (zoneM.PoolID == -2) continue;
                if (zoneM.PoolID == -1)
                {
                    zoneM.PoolID = list.Count;
                    ConnectedZones<T1, T2> connectedDomain = new ConnectedZones<T1, T2>();
                    connectedDomain.Zones.Add(zones[zoneM.IndexInList]);
                    list.Add(connectedDomain);
                }
                else
                {
                    list[zoneM.PoolID].Zones.Add(zones[zoneM.IndexInList]);
                }
                foreach (var zb in zoneM.LinkedZoneID_Bigger)
                {
                    ZonesMirror[zb].PoolID = zoneM.PoolID;
                }
            }
            //contact
            for (int i1 = 0; i1 < contacts.Count; i1++)
            {
                contacts[i1].GetONZoneID(out int OID, out int NID);
                int inPoolID = ZonesMirror[OID].PoolID;
                list[inPoolID].Contacts.Add(contacts[i1]);
            }
            return list;
        }
        public class ZoneMirror
        {
            public int PoolID;//-2表示无该区域，-1表示有该区域暂时没分配到pool
            public int IndexInList;//在传入的list中的位置
            public List<int> LinkedZoneID_Bigger = new List<int>();
        }
        public class ConnectedZones<T1, T2>
        {
            public List<T1> Zones { get; set; } = new List<T1>();
            public List<T2> Contacts { get; set; } = new List<T2>();
        }
    }
}